/*
 *  Copyright (c) 2011 Leibniz Institute of Plant Genetics and Crop Plant Research (IPK), Gatersleben, Germany.
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the GNU Lesser Public License v2.1
 *  which accompanies this distribution, and is available at
 *  http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 *
 *  Contributors:
 *      Leibniz Institute of Plant Genetics and Crop Plant Research (IPK), Gatersleben, Germany - RMI Client, FileChooser and WebDAV
 */
/*

 Copyright 2011 North Concepts Inc.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.

 */
package de.ipk_gatersleben.bit.bi.edal.webdav.wrapper;

import io.milton.http.exceptions.BadRequestException;
import io.milton.http.exceptions.NotAuthorizedException;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.bind.JAXBException;

import io.milton.common.Path;
import io.milton.http.HttpManager;
import io.milton.http.ResourceFactory;

import de.ipk_gatersleben.bit.bi.edal.primary_data.file.PrimaryDataDirectoryException;
import de.ipk_gatersleben.bit.bi.edal.primary_data.file.PrimaryDataEntityVersionException;
import de.ipk_gatersleben.bit.bi.edal.primary_data.metadata.MetaDataException;
import de.ipk_gatersleben.bit.bi.edal.primary_data.security.EdalAuthenticateException;
import de.ipk_gatersleben.bit.bi.edal.rmi.client.ClientDataManager;
import de.ipk_gatersleben.bit.bi.edal.webdav.wrapper.primary_data.PrimaryDataDirectoryResource;
import de.ipk_gatersleben.bit.bi.edal.webdav.wrapper.primary_data.PrimaryDataEntityPropertyVirtualResource;
import de.ipk_gatersleben.bit.bi.edal.webdav.wrapper.primary_data.PrimaryDataEntityResource;
import de.ipk_gatersleben.bit.bi.edal.webdav.wrapper.primary_data.PrimaryDataFileDirectoryVirtualResource;
import de.ipk_gatersleben.bit.bi.edal.webdav.wrapper.primary_data.PrimaryDataFileResource;
import de.ipk_gatersleben.bit.bi.edal.webdav.wrapper.primary_data.PrimaryDataVersionDirectoryVirtualResource;

public class EdalResourceFactory implements ResourceFactory {

	public EdalResourceFactory() {

	}

	@Override
	public io.milton.resource.Resource getResource(String host, String strPath)
			throws NotAuthorizedException, BadRequestException {
		Path path = Path.path(strPath);
		FileSystemHandler fileSystemHandler = null;
		if (HttpManager.request().getAuthorization() != null) {
			String username = HttpManager.request().getAuthorization()
					.getUser();
			if (username != null) {
				fileSystemHandler = FileSystemCache.get(username);
			}
		}

		try {
			if (path.isRoot()) {
				return new PrimaryDataDirectoryResource("/", fileSystemHandler);
			} else {
				if (fileSystemHandler == null) {
					return null;
				}
				String file = path.toString();

				int index = file
						.indexOf(FileSystemHandler.VIRTUALVERSIONFOLDERPREFIX);
				if (index >= 0) {
					String realpath = file.substring(0, index)
							+ file.substring(index
									+ FileSystemHandler.VIRTUALVERSIONFOLDERPREFIX
											.length());

					int ipos = realpath.indexOf("/"
							+ FileSystemHandler.VIRTUALFILEPREFIX);
					while (ipos >= 0) {
						realpath = realpath.substring(0, ipos + 1)
								+ realpath.substring(ipos
										+ 1
										+ FileSystemHandler.VIRTUALFILEPREFIX
												.length());
						ipos = realpath.indexOf("/"
								+ FileSystemHandler.VIRTUALFILEPREFIX);
					}

					ipos = realpath.indexOf("/"
							+ FileSystemHandler.VIRTUALFOLDERPREFIX);
					while (ipos >= 0) {
						realpath = realpath.substring(0, ipos + 1)
								+ realpath.substring(ipos
										+ 1
										+ FileSystemHandler.VIRTUALFOLDERPREFIX
												.length());
						ipos = realpath.indexOf("/"
								+ FileSystemHandler.VIRTUALFOLDERPREFIX);
					}

					// filter virtual files
					Pattern virtual = Pattern
							.compile("(.*)\\.v[0-9]+\\.?[^\\.]*\\.(properties?\\.?xml|.*)$");
					Matcher vm = virtual.matcher(realpath);

					if (vm.matches()) {
						Pattern property = Pattern
								.compile(".*\\.v[0-9]+\\.?[^\\.]*\\.properties\\.xml$");
						Matcher pm = property.matcher(realpath);

						if (!pm.matches()) {
							return new PrimaryDataFileDirectoryVirtualResource(
									vm.group(1) + "." + vm.group(2),
									fileSystemHandler).child(realpath);
						} else {
							PrimaryDataEntityPropertyVirtualResource virtualxmlresouce = new PrimaryDataEntityPropertyVirtualResource(
									realpath, fileSystemHandler);
							return virtualxmlresouce;
						}
					} else {
						PrimaryDataEntityResource entr = new PrimaryDataEntityResource(
								realpath, fileSystemHandler);

						if (entr.exists()) {
							if (entr.isDirectory()) {

								return new PrimaryDataVersionDirectoryVirtualResource(
										entr.getEntity().getPath(),
										fileSystemHandler);
							} else {

								return new PrimaryDataFileDirectoryVirtualResource(
										entr.getEntity().getPath(),
										fileSystemHandler);
							}
						}

					}
				} else {
					Pattern property = Pattern
							.compile(".*\\.v[0-9]+\\.?[^\\.]*\\.properties\\.xml$");
					Matcher pm = property.matcher(file);
					if (!pm.matches()) {
						PrimaryDataEntityResource entr = new PrimaryDataEntityResource(
								file, fileSystemHandler);
						/*
						 * win7 looks for non existing files e.g.
						 * 'desktop.ini','folder.gif','folder.jpg'
						 */
						if (entr.exists()) {
							if (entr.isDirectory()) {
								if (entr.getEntity() == null) {
									return null;
								}

								return new PrimaryDataDirectoryResource(entr
										.getEntity().getPath(),
										fileSystemHandler);
							} else {
								if (entr.getEntity() == null) {
									return null;
								}

								return new PrimaryDataFileResource(entr
										.getEntity().getPath(),
										fileSystemHandler);
							}
						}
					} else {
						PrimaryDataEntityPropertyVirtualResource virtualxmlresouce = new PrimaryDataEntityPropertyVirtualResource(
								file, fileSystemHandler);
						return virtualxmlresouce;
					}
				}

			}
		} catch (NotBoundException e) {
			ClientDataManager.logger.error("Failed handling request for file: "
					+ strPath + "\nReason: " + e.toString());
		} catch (RemoteException e) {
			ClientDataManager.logger.error("Failed handling request for file: "
					+ strPath + "\nReason: " + e.toString());
		} catch (PrimaryDataDirectoryException e) {
			ClientDataManager.logger.error("Failed handling request for file: "
					+ strPath + "\nReason: " + e.toString());
		} catch (EdalAuthenticateException e) {
			ClientDataManager.logger.error("Failed handling request for file: "
					+ strPath + "\nReason: " + e.toString());
			throw new NotAuthorizedException("don't support this operation!",
					null);
		} catch (JAXBException e) {
			ClientDataManager.logger.error("Failed handling request for file: "
					+ strPath + "\nReason: " + e.toString());
		} catch (PrimaryDataEntityVersionException e) {
			ClientDataManager.logger.error("Failed handling request for file: "
					+ strPath + "\nReason: " + e.toString());
		} catch (MetaDataException e) {
			ClientDataManager.logger.error("Failed handling request for file: "
					+ strPath + "\nReason: " + e.toString());
		}

		return null;
	}

}